<?php

namespace appApi\method;

use appApi\components\RequestFormat;
use appApi\components\ResultStatus;
use appApi\components\Utils;
use appApi\dao\AppApi as AppApiDao;
use common\dao\PrivateLetterDao;
use yii\base\Object;
use yii\helpers\Json;
use Yii;

/**
 * 接口方法处理的基类
 * @package appApi\method
 */
class BaseMethod extends Object implements IMethod
{
    /**
     * @var Object 处理后结果
     */
    protected $result;
    /**
     * @var int 处理结果状态值
     */
    protected $status = ResultStatus::SUCCESS;
    /**
     * @var string 错误信息
     */
    protected $error;
    /**
     * @var array 业务信息
     */
    protected $errorData = [];
    /**
     * @var \app\models\AccessToken 访问授权
     */
    protected $accessToken;
    /**
     * @var \appApi\components\ApiParameters 请求的参数
     */
    protected $parameters;
    /**
     * @var bool 是否是游客
     */
    protected $isGuest = true;
    /**
     * @var bool 是否验证登录
     */
    public $verifyLogin = false;
    /**
     * @var array 请求的业务参数
     */
    protected $data = null;
    /**
     * @var null|int|string 登录用户的ID
     */
    protected $userId;

    public function getResult()
    {
        return $this->result;
    }

    public function getStatus()
    {
        return $this->status;
    }

    public function getError()
    {
        return $this->error;
    }

    public function setAccessToken($accessToken)
    {
        $this->accessToken = $accessToken;
    }

    public function setParameters($params)
    {
        $this->parameters = $params;
        $this->formatData();
    }

    /**
     * 错误日志
     * @param $message
     */
    protected function errorLog($message)
    {
        Yii::error($message, 'appApi');
    }

    /**
     * 调试日志
     * @param $message
     */
    protected function traceLog($message)
    {
        Yii::trace($message, 'appApi');
    }

    /**
     * 格式化业务数据
     */
    protected function formatData()
    {
        $data = $this->parameters->data;
        if(!$data) {
            return;
        }
        $dataObj = null;
        switch($this->parameters->format) {
            case RequestFormat::JSON:
            case RequestFormat::JSONP:
                try {
                    $dataObj = Json::decode($data);
                } catch (\Exception $e) {
                    $this->status = ResultStatus::REQUEST_FORMAT_ERROR;
                    $this->error = '格式化业务数据错误, ' . $e->getMessage();
                }
                break;
            case RequestFormat::XML:
                try {
                    $dataObj = $this->xmlToArray($data);
                } catch (\Exception $e) {
                    $this->status = ResultStatus::REQUEST_FORMAT_ERROR;
                    $this->error = '格式化业务数据错误, ' . $e->getMessage();
                }
                break;
            default:
                $this->status = ResultStatus::REQUEST_FORMAT_ERROR;
                $this->error = '数据格式现只支持：JSON,XML,JSONP.';
                break;
        }
        $this->data = $dataObj;
    }

    /**
     * xml to array
     * @param $xml
     * @return mixed
     */
    protected function xmlToArray($xml)
    {
        $array_data = Json::decode(
            Json::encode(
                simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)
            )
        );
        return $array_data;
    }

    public function getData()
    {
        return $this->data;
    }

    /**
     * 获取业务参数中得数据项
     * @param string $key
     * @param null|Object $defaultValue
     * @return null|array
     */
    protected function getDataItem($key, $defaultValue=null)
    {
        return $this->data && isset($this->data[$key]) ? $this->data[$key] : $defaultValue;
    }

    /**
     * 验证用户登录信息
     * @return bool
     */
    protected function verifyUserAuth()
    {
        if(empty($this->parameters->userToken)) {
            $this->isGuest = true;
            if($this->verifyLogin) {
                $this->status = ResultStatus::USER_TOKEN_ERROR;
                $this->error = '用户授权错误';
            }
            return false;
        }
        //加入活动
        try{
            $userAuth = AppApiDao::userAuthInfo($this->accessToken->id, $this->parameters->userToken);
        }catch(\Exception $e){
            $userAuth = AppApiDao::userTokenInfo($this->parameters->userToken);
        }
        if($userAuth == false || $userAuth->state != 1) {
            $this->isGuest = true;
            if($this->verifyLogin) {
                $this->status = ResultStatus::USER_TOKEN_EXPIRES;
                $this->error = '用户授权失效';
            }
            return false;
        }
        $this->isGuest = false;
        $this->userId = $userAuth->user_id;
        return true;
    }

    protected function run()
    {
        throw new \Exception('null method');
    }

    /**
     * 保存用户授权信息
     * @param $userId
     * @return bool|string user token
     */
    protected function saveUserAuth($userId)
    {
        $token = Utils::createToken();
        if(AppApiDao::addUserAuth($this->accessToken->id, $userId, $token)) {
            return $token;
        }
        return false;
    }

    /**
     * 执行处理
     * @throws \Exception
     */
    public function handle()
    {
        if($this->status != ResultStatus::SUCCESS) {
            return;
        }
        $this->verifyUserAuth();
        // 验证登录
        if($this->verifyLogin && $this->isGuest) {
            return;
        }
        //检查封号
        $this->chatPunish();
        ob_start();
        $result = $this->run();
        $out = ob_get_clean();
        if($result) {
            $this->result = $result;
        } elseif (empty($out) == false) {
            $this->result = $out;
        } else {
            $this->result = is_array($result) ? [] : '';
        }
    }
    /**
     * 验证参数完整性
     * @param $array
     */
    protected function verifyParameter($array){
        foreach($array as $key=>$val){
            if(!isset($val)){
                return true;
                break;
            }
        }
        return false;
    }
    /**
     * 封号处理
     * @return bool
     */
    public function chatPunish(){
        //检查禁封账号
        $chatPunish = PrivateLetterDao::chatPunish($this->userId,2);
        if(!empty($chatPunish)){
            $this->status = ResultStatus::USER_TOKEN_DISABLE;
            $this->error = '该账号被封号'.$chatPunish['punishInterval'].'天';
            return false;
        }
        return true;
    }
}